/** @jsxImportSource @emotion/react */
import * as React from "react";
import {
    useTheme,
    Text,
    IconButton,
    IconArrowLeft,
    TwoHalfRightPanel,
    InputLine,
    Select,
    CommitInput,
    ButtonRefComp,
    SuffixInput,
    LineColumn,
    Container,
    CheckSwitch,
    VerticalMenu,
    DdMenuItem,
    InputGroup,
    TextArea,
    InputDatalist,
    Input,
    Button,
    Toolbar, Navbar,
} from "customize-easy-ui-component";

// import { Link as RouterLink } from "../../routing/Link";
import {PreloadedQuery, usePreloadedQuery, useRefetchableFragment} from "react-relay/hooks";
// import {TechnicalConfigQuery, TechnicalConfigQuery$data} from "./__generated__/TechnicalConfigQuery.graphql";
//import {noop} from "use-media/lib/utilities";

// import {DivisionChooseQuery$data} from "../../unit/division/__generated__/DivisionChooseQuery.graphql";
import {Dispatch, MutableRefObject, SetStateAction, useContext, useEffect} from "react";

import {
    Disposable,
} from 'relay-runtime';
// import useUpdateDetailMutation from "./useUpdateDetailMutation";
import {InternalEditorResult} from "../common/base";
// import useBui`ldRequestMutation from "../hook/useBuildRequestMutation";
// import {层门形式} from "../../device/edit/升降机";
// import {设备同步作业} from "../../maintenance/DeviceMaint";
import {ChooseEqps} from "../comp/ChooseEqps";
import RoutingContext from "../routing/RoutingContext";
// import {useMainConfig} from "../hook/useMainConfig";
import {MainQuery, MainQuery$data} from "./__generated__/MainQuery.graphql";
import {EqpOpenclose} from "./edit/EqpOpenclose";
import {DeviceUnits} from "./edit/DeviceUnits";
import useBuildAgreementMutation from "../agreement/hook/useBuildAgreementMutation";
import useBuildRequestMutation from "./hook/useBuildRequestMutation";
import {OneUserChoose} from "../common/user/OneUserChoose";
import {RevisionPermit} from "./edit/RevisionPermit";
import {RevisionExecution} from "./edit/RevisionExecution";
import {AloneContainer} from "../comp/AloneContainer";
import {Main$data, Main$key} from "./__generated__/Main.graphql";
import {RefetchFnDynamic} from "react-relay/relay-hooks/useRefetchableFragmentNode";
import {StopInspec} from "./edit/StopInspec";
import {requestStatusMap} from "./RequestList";
import {RequestTypeMap} from "./AddToRequest";
import {TaskExceptionDeal} from "./edit/TaskExceptionDeal";
import {TechnicalField} from "./edit/TechnicalField";
// import {TwoHalfRightPanel} from "../../../UiDebugSave/sample/TwoHalfRightPanel";
// import {MainQuery$data} from "../hook/__generated__/useMainConfigQuery.graphql";
// import {会计项目录} from "../../dict/financeComm";

//import useReckonIspFeeMutation from "./useReckonIspFeeMutation";
//[HOOK限制]按钮点击函数内部直接上toast()或toaster.notify()很可能无法正常显示。而放在函数组件顶层render代码前却能正常。
const graphql = require("babel-plugin-relay/macro");

interface DetailConfigProps {
    id?: string;
    prepared: {
        //【特别注意】query路由器若不是提供这个类型的查询DetailConfigQuery，本组件也不会抛出异常！在usePreloadedQuery<DetailConfigQuery>()不报错！
        query: PreloadedQuery<MainQuery>;
    }
    children: React.ReactNode;
    routeData: any;
}

/**右边的主要编辑内容
 * */
export default function Main(props: DetailConfigProps) {
    // const {frame,sibling,agreement,editorRef} =useMainConfig(props);
    const theme = useTheme();
    //后端非结构化json字段的内部内容无法内省dat内省报错: Expected no selections on scalar field `dat`
    // const data = usePreloadedQuery<MainQuery>(
    //     graphql`
    //         query MainQuery($rqId: ID!) {
    //             node(id: $rqId)
    //             {
    //                 id, __typename
    //                 ... on Request {
    //                     id,status,ispu{id name}, crman{id username},
    //                     auditor{id username,person{id,name}}, director{id username,person{id,name}},
    //                     manager{id username,person{id,name}},
    //                     mdtime, mod,
    //                     dat,audat,result,mndat,drdat
    //                 }
    //             }
    //         }
    //     `,
    //     props.prepared.query,
    // );
    // const { node:item, }=data;    //有多个分项报告[SimpleReport]
    // node(id: $rqId){
    //     id, __typename
    // ... on Request {
    //         id,status,ispu{id name}, crman{id,username,person{id,name},dep{id,name},office{id,name}},
    //         auditor{id username,person{id,name}}, director{id username,person{id,name}},
    //         manager{id username,person{id,name}},
    //         mdtime, mod,
    //             dat,audat,result,mndat,drdat
    //     }
    // }

    const data = usePreloadedQuery<MainQuery>(
        graphql`
            query MainQuery(
                $rqId:ID!,
            ) {
                ...Main
            }
        `,
        props.prepared.query,
    );
    //const { node:item, }=data;     //通常接收方式
    //useRefetchableFragment用法特别必须首先上usePreloadedQuery之后嵌套儿子组件或者顺序上跟着的Hook: #实际上 输出数据类型被下面替换掉了！
    //父辈组件直接跟随（原本应该是放入子组件）的Refetchable查询 ：可是通常应该放入儿子组件当中的。
    const [datanode, refetch] = useRefetchableFragment(
        graphql`
            fragment Main on Query
            @refetchable(queryName: "MainRefetchQuery") {
                node(id: $rqId)
                {
                    id, __typename
                    ... on Request {
                        id,status,ispu{id name}, crman{id,username,person{id,name},dep{id,name},office{id,name}},
                        auditor{id username,person{id,name}}, director{id username,person{id,name}},
                        manager{id username,person{id,name}},
                        mdtime, mod,
                        dat,audat,result,mndat,drdat
                    }
                }
            }
        `,
        data as Main$key,
    );
    //上面的data必须再次声明类型的 as OneAgreementMain$key,。依赖于Relay编译器生成代码。
    //为了支持refetch引进： 必须再一次接收数据datanode。
    //上面的"OneAgreementMainRefetchQuery")必须直接声明devs{}若使用...AgreementBoundDevices来声明的很可能无法提取出来devs,复用缺点@必须一致的提前声称字段。
    const { node:request, }=datanode;

    const {call:updateDetailFunc,doing,called, result}= {} as any// useBuildRequestMutation();
    //  const {call:cudChFeefunc, doing, called, reset, result:cudAck}= useCudChargingFeeMutation();     //删除专用，增加在子组件内部独立的；

    //先试一试：直接在父辈同一个组件内直接做 编辑器方式的保存。 PreloadedQuery+Mutation()都在同一组件干。
    // const [ccost, setCcost] = React.useState<number|undefined>(item?.ccost!);
    // const [fcode, setFcode] = React.useState(item!.fcode);
    // const [zmoney, setZmoney] = React.useState(item?.zmoney);
    // const [totm, setTotm] = React.useState<number|undefined>(item!.totm!);
    //会根据参数判定输出类型啊！报错了,useRef<T>(initialValue: T|null): RefObject<T>; useRef<T>(initialValue: T): MutableRefObject<T>;
    const editorRef=React.useRef({} as InternalEditorResult);
    const {save, field, reurl, p1field, multi}= window.history.state?.state??{};       //通用伪对话框传递格式field=上次跳转目标选择字段。
    const {history } = useContext(RoutingContext);

    console.log("收费主页来taskSjw:", props.routeData.params.taskId!,";routeData=", props.routeData, "editorRef=",editorRef.current);
    if(!data)  throw new Error(`没找到协议申请单 ID${props.id}`);
//为了比较适合打印改造成居中单独页面，而不是TwoHalf框架的页面。完美打印的文书需要专门打印机适配页面才好。
    return (
        <AloneContainer css={{
            background: 'white',
            alignItems: 'unset',
            maxWidth: '794px',    //A4纸张 或者电脑屏幕限制宽
            "@media print": {
                margin: 'unset',       //小于一页纸高度的就不要居中
            },
        }}>
            <RequestMainInner det={request} editorRef={editorRef} refetch={refetch}/>
        </AloneContainer>
    );
};



export const 验收形式和方法 =['报告、道路运输液体危险货物罐式车辆常压容器（罐体）定期检验报告FJB/RC 1038-2015；',
    '其他'];
export const 支付方式 =['一次性支付','其他'];


/**
 * 为了避免把保存按钮也一起放入到编辑器组件中，还能把编辑后的属性数据全部提供给父辈组件，
 * 真正mutation接口函数操作+按钮触发:直接安排在上一级组件内做的。
 * 【通用模式】规定统一的数据修改保存的模式：引进专有的props.editorRef.doConfirm():来做规范和统一处理。
* */
interface Props {
    //从上级获取老的字段属性数据:  Request 模型;
    //det: MainQuery$data["node"]; 直接从父辈组件自动产生的graphQL定义文件接收
    det: Main$data["node"];
    //正常情形editorRef不应该是null的，上级组件必须有保存触发按钮的;
    //通用的编辑器：字段属性被修改之后，必须回传编辑好的字段 新数据给上级组件。editorRef对上级组件暴露编辑器数据。editorRef.doConfirm()最好保持一样名字
    editorRef?: MutableRefObject<InternalEditorResult>;
    //只能这样声明 泛型的 类型了：
    refetch: RefetchFnDynamic<any, any>;
}
/**业务信息配置--编辑器主体子组件*/
function RequestMainInner({det, editorRef,refetch}: Props) {
    const theme = useTheme();
    // const commitBlurRef =React.useRef<HTMLDivElement | null>(null);
    //设备类型：EQP_TYPE 有些是单独报告的没关联设备台账的。 det?.type优先承认的。
    // const type= det?.;
    const {save, field}= window.history.state?.state??{};      //通用伪对话框传递格式field=上次跳转目标选择字段。
    //业务类型: OPE_TYPE ;
    // const ope= det?.bsType;
    // const [ptno, setPtno] = React.useState(det!.ptno);
    // //默认委托的 technical
    // const [bsType, setBsType] = React.useState(save? save.bsType : det?.bsType);
    // const [entrust, setEntrust] = React.useState(det?.entrust);
    // const [transferor, setTransferor] = React.useState(save? save.transferor : det?.transferor);
    // const [complDate, setComplDate] = React.useState(save? save.complDate : det?.complDate);
    // const [charge, setCharge] = React.useState(save? save.charge : det?.charge);
    // const [dxDevs, setDxDevs,] = useStorageState<[]>(
    //     sessionStorage,
    //     '设备多选集'
    // );
    //[特殊问题] save遗留：就算刷新页面也会留存旧的save除非URL页面路由更新跳转后再点击路由回来，save才会丢失。手动退出编辑状态，devs和编辑器其它选择跳转编辑影响。一个页面有两组的设备选择组件devs1[]devs2[]不支持吧。
    //编辑模式从未对话框页面跳转返回后才会有save.devs ，而Relay读取送到det?.devs ?多个设备同样的申请单修订？ 单一个单位修正。
    // const [devs, setDevs] = React.useState(save? save.devs : det?.devs);
    const  dat = save? save.dat :  JSON.parse(det?.dat || '{}');

    const {call:updateDetailFunc,doing,called, result}= useBuildRequestMutation();
    const curFlow=sessionStorage['审批单']&&JSON.parse(sessionStorage['审批单']);

    function confirmation() {
        const dat={ };
        return {
            // ptno, entrust, bsType, transferor, complDate, charge,
            // devs: devs?.map((eqp: { id: any; })=>eqp.id),
            dat: JSON.stringify(dat)
        };
    }
    //[反过来诡异？]简易方式暴露ref操作接口给上级组件 ，让父辈组件的按钮能够直接执行子组件的回调钩子函数
    editorRef!.current = { doConfirm: confirmation } as InternalEditorResult;
    const {history } = useContext(RoutingContext);
    const myUrl= history.createHref(history.location);
    const hrefnow =history.location.pathname;

    //流转可能遇见两个人物：auditor审核人 或者 dispatcher最终责任人
    // const [auditor, setAuditor] = React.useState<any>(det?.auditor);

    //todo:根据子组件的相似性程度，还可以考虑复用hook拆解装配模式组装可复用代码？不是每次都是全部复制拷贝的。

    return (
        <Container>
            <div css={{
                // paddingTop: theme.spaces.lg,
                paddingBottom: theme.spaces.lg
            }}>
                <Navbar  position="static"
                         css={{
                             backgroundColor: "white",
                         }}
                >
                    <Toolbar  compressed
                        css={{
                            alignItems: "center",
                            display: "flex",
                        }}
                    >
                        <Text
                            css={{
                                flex: 1,
                                textAlign: "center",
                            }}
                            wrap={false}
                            variant="h5"
                            gutter={false}
                        >
                            {RequestTypeMap.get(det?.mod!)}
                        </Text>
                        <VerticalMenu>
                            <DdMenuItem label="刷新本申请单" onPress={async () => {
                                    await refetch({first:4,},{fetchPolicy: "network-only"});
                                    //最后依靠useMyMutation(){ updater: {request.invalidateRecord();来主动把数据拉成失效，下次进入需要该数据的组件自动重新获取来解决问题，其它办法不好使！
                                    //@实际上真没效果的！导致组件render一次！但是组件不会remount的Input无法自动变动。初始化好的内容无法自动变动;务必等待data有变动再去.push(myUrl#
                                    history.replace(myUrl, {time: Date()} );
                                    //history.push(history.location.pathname+'#tm_'+Date());
                                    //若用 history.go(0);  //等同浏览器点击强制刷新，代价昂贵，代码数据完全刷新的,但是浏览器Session存储没清空。
                                    //数据加载没法导致没有remount的Input编辑框自动更新，只能浏览器前进后退才会remount。
                                }
                            }
                            />
                            <DdMenuItem label="删除申请单"
                                        onPress={() => {
                                        }} />
                        </VerticalMenu>
                    </Toolbar>
                </Navbar>
                <Text variant="h5">申请单当前状态： {requestStatusMap.get(det?.status!)}</Text>
                {
                    (det?.status==='END' || det?.status==='FIN') &&
                    <Text variant="h6">已有结果： {det?.result}</Text>
                }
                { (curFlow?.entId === det?.id && curFlow?.pren) &&
                    <Text variant="h6">是从节点 {curFlow?.pren} 流转过来的。</Text>
                }
                <Text variant="h6">申请人：{det?.crman?.dep?.name||'-'} {det?.crman?.office?.name ||'-'} {det?.crman?.person?.name || '?'}</Text>

                { det?.mod==='eqpOpenclose' && (
                    <EqpOpenclose  readOnly={true} editable={true}  req={det} mutationFunc={updateDetailFunc} curFlow={curFlow}/>
                ) }
                { det?.mod==='deviceUnits' && (
                    <DeviceUnits  readOnly={true} editable={true}  req={det} mutationFunc={updateDetailFunc} curFlow={curFlow}/>
                ) }
                { det?.mod==='revisionPermit' && (
                    <RevisionPermit  readOnly={true} editable={true}  req={det} mutationFunc={updateDetailFunc} curFlow={curFlow}/>
                ) }
                { det?.mod==='revisionExecution' && (
                    <RevisionExecution  readOnly={true} editable={true}  req={det} mutationFunc={updateDetailFunc} curFlow={curFlow}/>
                ) }
                { det?.mod==='stopInspec' && (
                    <StopInspec  req={det} mutationFunc={updateDetailFunc} curFlow={curFlow}/>
                ) }
                { det?.mod==='technicalField' && (
                    <TechnicalField  req={det} mutationFunc={updateDetailFunc} curFlow={curFlow}/>
                ) }
                { (det?.mod==='taskDelay' || det?.mod==='cancelTask') && (
                    <TaskExceptionDeal  req={det} mutationFunc={updateDetailFunc} curFlow={curFlow}/>
                ) }
            </div>
        </Container>
    );
}

